
check_error <- function(cur_line = c(), error_p = c(), answer = 1){
  cur_value <- sum(cur_line * c(error_p, 1))
  if(cur_value * answer <= 0){
    return(T)
  }else{
    return(F)
  }
}


line_fix  <- function(cur_line = c(), error_p = c(), answer = 1){
  if(length(error_p) != (length(cur_line) - 1)){
    warning("Length Not Conincide")
    return(NA)
  }
  if(answer > 0){
    return(cur_line + c(error_p, 0))
  }else{
    return(cur_line - c(error_p, 0))
  }
}

over_all_right_ratio <- function(data = data.frame(), cur_line = c()){
  right_vec <- 0
  for(i in 1:dim(data)[1]){
    ## found point
    error_p <- as.vector(data[i,c(1:(dim(data)[2] - 1))])
    names(error_p) <- NULL
    error_p <- as.matrix(error_p, nrow = 1)[1,]
    if(check_error(cur_line = cur_line, error_p = error_p, answer = data$answer[i]) == F){
      ## if answer is right
      right_vec[i] <- 1
    }else{
      right_vec[i] <- 0
    }
  }
  right_num <- sum(right_vec)
  err_num <- sum(right_vec - 1) * (-1)
  if(right_num >= err_num){
    need_trans <- F
    out_ratio <- right_num / dim(data)[1]
    out_string <- c(1:dim(data)[1])[right_vec == 0]
  }else{
    need_trans <- T
    out_ratio <- err_num / dim(data)[1]
    out_string <- c(1:dim(data)[1])[right_vec == 1]
  }
  return(list(need_trans, out_ratio, out_string))
}

# test function:
# over_all_right_ratio(data = data, cur_line = c(1, -1, 1))
# over_all_right_ratio(data = data, cur_line = cur_line)
# over_all_right_ratio(data = data, cur_line = total_lines[3,])
#### my perceptron ####

my_perceotron <- function(data = data.frame(), split_percent = 0.90, max_loop = 10000){
  ## centralize data
  names(data) <- c(paste("v", 1:(dim(data)[2] - 1), sep = ""), "answer")
  
  #### record total means in tem_record
  tm_record <- 0
  i = 1
  for(i in 1:(dim(data)[2] - 1)){
    g1m <- mean(data[data$answer == 1, i])
    g2m <- mean(data[data$answer == -1, i])
    tm <- mean(c(g1m, g2m))
    tm_record[i] <- tm
    data[,i] <- data[,i] - tm
  }
  
  ### init lines
  total_lines <- matrix(c(rep(0, (dim(data)[2] - 1)), 1), byrow = T, ncol = dim(data)[2])
  line_right_ratio <- 0
  line_cursor  <- 1
  cur_line <- total_lines[line_cursor,]
  
  loop_num <- 1
  while(loop_num <= max_loop){
    #### check current line
    check_result <- over_all_right_ratio(data = data, cur_line = cur_line)
    cat("\nLine number:", loop_num,"\nCorrect Ratio", check_result[[2]], sep = "")
    #### if need trans, trans the line
    if(check_result[[1]]){
      total_lines[line_cursor,] <- total_lines[line_cursor,] * (-1)
    }
    #### record right ratio
    right_ratio <- check_result[[2]]
    line_right_ratio[line_cursor] <- right_ratio
    #### set error_sample
    error_sample <- check_result[[3]]
    
    #### check whether need break
    if(length(error_sample) == 0){
      cat("\nAll Right!\n")
      break
    }
    
    if(check_result[[2]] >= split_percent){
      cat("\ncheck_result[[2]] = ", 
          check_result[[2]],"\nright_ratio = ",
          right_ratio,
          "\nspilt_percent = ", split_percent,
          "\nSatisfied split_percent requirment\n")
      break
    }
    
    #### choose fix base point
    data_cursor <- sample(error_sample, 1)
    
    #### clean error point's data
    error_p <- as.vector(data[data_cursor,c(1:(dim(data)[2] - 1))])
    names(error_p) <- NULL
    error_p <- as.matrix(error_p, nrow = 1)[1,]
    
    ## fix the line
    fixed_line <- line_fix(cur_line = cur_line, 
                           error_p = error_p, 
                           answer = data$answer[data_cursor])
    
    ## add new line to total line pool
    total_lines <- matrix(c(as.vector(total_lines), fixed_line), ncol = dim(data)[2], byrow = T)
    
    # update line cursor
    line_cursor <- line_cursor + 1
    cur_line <- total_lines[line_cursor,]
    
    ## add loop num
    loop_num <- loop_num + 1
  }
  
  ## update new line matrix
  new_total_lines <- total_lines
  for(i in 1:dim(new_total_lines)[1]){
    for(j in 1:(dim(new_total_lines)[2] - 1)){
      new_total_lines[i,dim(new_total_lines)[2]] <- new_total_lines[i,dim(new_total_lines)[2]] - new_total_lines[i, j] * tm_record[j]
    }
  }
  return(list(new_total_lines, line_right_ratio))
}

#### TEST AREA ####

# ## create data
# fakedatax <- c(rnorm(1000, 6, 0.7), rnorm(500, 4, 1))
# fakedatay <- c(rnorm(1000, 4, 1.5), rnorm(500, 0, 0.7))
# 
# answer <- c(rep(1,1000), rep(-1, 500))
# datain <- data.frame(fakedatax, fakedatay, answer)
# 
# 
# ## plot only data
# library(ggplot2)
# color <- c(rep("a", 1000), rep("b", 500))
# ggplot(datain, aes(x = fakedatax, y = fakedatay, color = color)) + geom_point()
# 
# #### loop display
# 
# result_temp <- my_perceotron(data = datain, split_percent = 0.98, max_loop = 1000)
# new_total_lines <- result_temp[[1]]
# for(i in 2:dim(new_total_lines)[1]){
#   plot_df <- data.frame(fakedatax, fakedatay, color)
#   plot_line_cursor <- i
#   plot_line <- new_total_lines[plot_line_cursor,]
#   
#   source("https://gitee.com/ry2an/my_public_functions_r/raw/master/ggplot_add_line_df.R")
#   plot_df <- rbind(plot_df, points_line(x_interval = c(-3, 8),
#                                         formula = line_to_plot_formula(plot_line),
#                                         precise = 1000,
#                                         type_code = "c",
#                                         typename = "color",
#                                         x_name = "fakedatax",
#                                         y_name = "fakedatay"
#   ))
#   
#   print(ggplot(plot_df, aes(x = fakedatax, y = fakedatay, color = color)) + geom_point())
# }
